﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
using SdmxMl.Manager;
using SdmxMl.Multiplexor;
using SdmxMl.Structure;

namespace SdmxMl.Panels
{
    /// <summary>
    /// Dialog to help composition of a subscription Item
    /// </summary>
    public partial class DlgSubscribeItem : Form
    {
        #region Internal Members

        public ArtefactComboSelector artefactsSelector;

        #endregion

        #region C'tor

        public DlgSubscribeItem(DataRow row)
        {
            InitializeComponent();

            // Fill combo Artefact types
            artefactsSelector = new ArtefactComboSelector(comboBoxArtefactType, comboBoxAgency, comboBoxArtefactId, comboBoxVersion);
            artefactsSelector.InitComboContent();
            // Existing subscription item to edit ?
            artefactsSelector.UpdateContent(row);
        }

        #endregion

        #region Submit Event

        private void buttonSubmit_Click(object sender, EventArgs e)
        {
            artefactsSelector.GetSelections();

            DialogResult = DialogResult.OK;
        }

        #endregion

    }

    /// <summary>
    /// Manages comboboxes for selection of artefacts request
    /// </summary>
    public class ArtefactComboSelector
    {
        #region Static Names

        public static string ColType = "TYPE";
        public static string ColAgency = "AGENCY";
        public static string ColArtefactId = "ARTEFACT";
        public static string ColVersion = "VERSION";

        public static string AnyMarker = "All";
        public static string latestVersion = "latest";

        #endregion

        #region Internal members

        private ComboBox comboBoxArtefactType;
        private ComboBox comboBoxAgency;
        private ComboBox comboBoxArtefactId;
        private ComboBox comboBoxVersion;

        private DataSet ds;

        #endregion

        #region Properties

        public SdmxArtefactType ArtefactType { get; private set; }
        public string CodedType { get; private set; }
        public string CodedAgency { get; private set; }
        public string CodedArtefact { get; private set; }
        public string CodedVersion { get; private set; }

        public bool RestSyntax { get; set; }

        /// <summary> Provides selected items as an array</summary>
        public object[] SelectionArray
        {
            get
            {
                return new object[] { CodedAgency, CodedType, CodedArtefact, CodedVersion, AnyMarker };
            }
        }

        #endregion

        #region C'tor

        // C'tor receives combo controls for managing selections
        public ArtefactComboSelector(ComboBox cbType, ComboBox cbAgency, ComboBox cbId, ComboBox cbVersion)
        {
            comboBoxArtefactType = cbType;
            comboBoxAgency = cbAgency;
            comboBoxArtefactId = cbId;
            comboBoxVersion = cbVersion;

            comboBoxArtefactType.SelectedIndexChanged += new EventHandler(comboBoxArtefactType_SelectedIndexChanged);
            comboBoxAgency.SelectedIndexChanged += new EventHandler(comboBoxAgency_SelectedIndexChanged);
            comboBoxAgency.TextUpdate += new EventHandler(comboBoxAgency_TextUpdate);
            comboBoxArtefactId.SelectedIndexChanged += new EventHandler(comboBoxArtefactId_SelectedIndexChanged);
            comboBoxArtefactId.TextUpdate += new EventHandler(comboBoxArtefactId_TextUpdate);
        }
        #endregion

        #region Initialisation

        public void InitComboContent()
        {
            comboBoxArtefactType.Items.Clear();
            comboBoxAgency.Items.Clear();
            comboBoxVersion.Items.Clear();


            // Fill combo Artefact types
            foreach (SdmxArtefactType atype in Enum.GetValues(typeof(SdmxArtefactType)))
            {
                // Type must be specified for Rest Syntax
                if (RestSyntax && atype == SdmxArtefactType.None)
                    continue;
                comboBoxArtefactType.Items.Add(new ComboArtefactTypeItem(atype));
            }
            comboBoxArtefactType.SelectedIndex = RestSyntax ? 2 : 0; // Default to codelist or All

            // Fill combo agencies with NSI agencies
            OrganisationSchemesType orgNsi = SdmxMl.Msg.HeaderGenerator.NSI_OrgScheme;

            // All is reserved word in 2.1 and cannot be used as agencyId so use it as regex marker
            comboBoxAgency.Items.Add(AnyMarker);
            if (orgNsi != null)
            {
                foreach (OrganisationType o in orgNsi.Agencies)
                    comboBoxAgency.Items.Add(o.Id);
            }
            comboBoxAgency.SelectedIndex = 0;

            comboBoxArtefactId.Items.Clear();
            comboBoxArtefactId.Items.Add(AnyMarker);


        }
        #endregion

        #region updates Combos content

        /// <summary>
        ///  Updates combos content according to selection embedded in datarow
        /// </summary>
        /// <param name="row">the row with selection for combo in its columns</param>
        public void UpdateContent(DataRow row)
        {
            // change marker for all
            if (row != null)
            {
                string typeAr = row[ColType].ToString();
                if (typeAr != AnyMarker && typeAr.Length > 4)
                {
                    // now try to retrive in combo
                    foreach (ComboArtefactTypeItem co in comboBoxArtefactType.Items)
                    {
                        if (co.ArType.ToString() == typeAr)
                        {
                            comboBoxArtefactType.SelectedItem = co;
                            break;
                        }
                    }
                }

                comboBoxAgency.SelectedIndex = -1;
                string AgencyId = row[ColAgency].ToString();
                comboBoxAgency.Text = AgencyId;

                comboBoxArtefactId.Text = row[ColArtefactId].ToString();

                comboBoxVersion.SelectedIndex = -1;
                comboBoxVersion.Text = row[ColVersion].ToString();
            }
        }
        #endregion

        #region Retrieves combo's content

        public void GetSelections()
        {
            CodedType = comboBoxArtefactType.SelectedIndex == 0 ? AnyMarker : comboBoxArtefactType.Text;
            ArtefactType = (comboBoxArtefactType.SelectedItem as ComboArtefactTypeItem).ArType;
            CodedAgency = IsAllSelected(comboBoxAgency.Text) ? AnyMarker : comboBoxAgency.Text;
            CodedArtefact = IsAllSelected(comboBoxArtefactId.Text.Trim()) ? AnyMarker : comboBoxArtefactId.Text.Trim();
            CodedVersion = IsAllSelected(comboBoxVersion.Text.Trim()) ? AnyMarker : comboBoxVersion.Text.Trim();

        }

        private bool IsAllSelected(string text)
        {
            return (text == "*" || text == string.Empty ||
                string.Compare(AnyMarker, text, true) == 0);
        }
        #endregion

        #region Combos Events

        private void comboBoxArtefactType_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateComboArtefactId();
        }

        private void comboBoxAgency_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateComboArtefactId();
        }

        private void comboBoxAgency_TextUpdate(object sender, EventArgs e)
        {
            UpdateComboArtefactId();
        }

        private void comboBoxArtefactId_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateComboVersion();
        }

        private void comboBoxArtefactId_TextUpdate(object sender, EventArgs e)
        {
            UpdateComboVersion();
        }

        /// <summary>
        /// If Internal NSI Agency Group selected, update combo with artefacts of group selected
        /// </summary>
        private void UpdateComboArtefactId()
        {
            ds = null;

            // Default
            List<string> aList = new List<string>();

            comboBoxArtefactId.Items.Clear();
            comboBoxArtefactId.Items.Add(AnyMarker);
            comboBoxArtefactId.Text = AnyMarker;

            //Do we need to fill
            if (comboBoxArtefactType.SelectedIndex > 0 && comboBoxAgency.Text.Length > 0)
            {
                using (new SdmxMl.Helper.CWaitCursor())
                {
                    string dummyFullId = comboBoxAgency.Text + "+1+1"; // required to determine registry
                    ds = Mux.Instance.DirInfo((comboBoxArtefactType.SelectedItem as ComboArtefactTypeItem).ArType.ToString(), dummyFullId);
                    if (ds != null && ds.Tables.Count > 0)
                    {
                        DataTable tb = ds.Tables[0];
                        foreach (DataRow row in tb.Rows)
                        {
                            if (row["AI"].ToString() == comboBoxAgency.Text)
                                if (aList.Contains(row["ID"].ToString()) == false)
                                    aList.Add(row["ID"].ToString());
                        }
                        comboBoxArtefactId.Items.Clear();
                        aList.Sort();
                        aList.Insert(0, AnyMarker);

                        comboBoxArtefactId.Items.AddRange(aList.ToArray());
                        comboBoxArtefactId.Text = AnyMarker;

                    }
                }
            }

            UpdateComboVersion();
        }


        /// <summary>
        /// If Internal NSI Agency Group and Artefact ID selected, update combo with versions of artefact selected
        /// </summary>
        private void UpdateComboVersion()
        {
            List<string> aList = new List<string>();

            comboBoxVersion.Items.Clear();
            comboBoxVersion.Items.Add(AnyMarker);
            if (RestSyntax)
                comboBoxVersion.Items.Add(latestVersion);
            comboBoxVersion.Text = AnyMarker;

            if (ds != null && ds.Tables.Count > 0)
            {
                DataTable tb = ds.Tables[0];
                foreach (DataRow row in tb.Rows)
                {
                    if (row["AI"].ToString() == comboBoxAgency.Text && row["ID"].ToString() == comboBoxArtefactId.Text)
                        if (aList.Contains(row["VER"].ToString()) == false)
                            aList.Add(row["VER"].ToString());
                }
                comboBoxVersion.Items.Clear();
                aList.Sort();
                if (RestSyntax)
                    aList.Insert(0, latestVersion);
                aList.Insert(0, AnyMarker);


                comboBoxVersion.Items.AddRange(aList.ToArray());
                comboBoxVersion.Text = AnyMarker;
            }
        }
        #endregion
    }
}
